package FlexTrade;

import java.rmi.RMISecurityManager;
import java.rmi.Remote;
import java.rmi.RemoteException;

import common_classes.IAuction;

import net.jini.config.Configuration;
import net.jini.config.ConfigurationException;
import net.jini.config.ConfigurationProvider;
import net.jini.core.entry.Entry;
import net.jini.core.lookup.ServiceID;
import net.jini.discovery.LookupDiscovery;
import net.jini.discovery.LookupDiscoveryManager;
import net.jini.export.Exporter;
import net.jini.lease.LeaseRenewalManager;
import net.jini.lookup.JoinManager;
import net.jini.lookup.ServiceIDListener;
import net.jini.lookup.entry.Name;

/*
 *main application 
 */

public class Market implements ServiceIDListener {
	
	static String LUS;
	static String CHECK_POINT_FILE_PATH;
	static String CONFIG_FILE;
	static String POLICY_FILE;
	static String CODE_BASE;
	static long CHECK_POINT_INTERVAL = 15000; //15s

	//==================================================
	//PUBLIC

	//==================================================
	
	protected MarketServiceImpl market_service;
	protected Remote proxy;
	
	protected AuthenticateImpl authenticate_service;
	protected Remote authenticateProxy;
	protected RemoteAccountsImpl remote_accounts;
	protected Remote remoteAccountsProxy;
	static public String[] args;
	private Configuration config;
	
	/**
	 * @param args
	 */
	
	public static void main(String[] args) {
		Market market = new Market(args);
		System.setProperty("java.security.policy",Market.POLICY_FILE);
		System.setSecurityManager(new RMISecurityManager());
		System.setProperty("java.rmi.server.codebase", Market.CODE_BASE);
		market.initializeServices();
		market.restoreFromCheckPoint();
		CheckPointScheduler scheduler = new CheckPointScheduler();
		scheduler.setMarket(market);
		Thread schedulerThread = new Thread(scheduler);
		schedulerThread.start();
		
		// stay around forever
		Object keepAlive = new Object();
		
		synchronized(keepAlive) {
			try {
				keepAlive.wait();
			} catch(InterruptedException e) {
				// do nothing  
			}
		}
	}
	
	
	public Market(String[] args)	{
		CONFIG_FILE = args[0];
		String[] configArgs = new String[] {Market.CONFIG_FILE};
		try {
			config = ConfigurationProvider.getInstance(configArgs);
			LUS = (String) config.getEntry("AppPara", "lus", String.class);
			CODE_BASE = (String) config.getEntry("AppPara", "codebase", String.class);
			POLICY_FILE = (String) config.getEntry("AppPara", "policyfile", String.class);
			CONFIG_FILE = (String) config.getEntry("AppPara", "configfile", String.class);
			CHECK_POINT_FILE_PATH = (String) config.getEntry("AppPara", "checkpointpath", String.class);
		} catch (ConfigurationException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			LUS = "jini://localhost/";
			CHECK_POINT_FILE_PATH = "/home/hieuht/auctionobjects.dat";
			CONFIG_FILE = "/home/hieuht/Eclipse/workspaceJEE/FlexTrade/src/FlexTrade/configFile.config";
			POLICY_FILE = "/home/hieuht/Eclipse/workspaceJEE/FlexTrade/src/FlexTrade/policy.txt";
			CODE_BASE = "http://localhost:9000/";
		}
	}
	
	public void initializeServices() {
		market_service = new MarketServiceImpl();		// market service
		authenticate_service = new AuthenticateImpl();	//authentication service
		remote_accounts = new RemoteAccountsImpl();		//remote bank service
		try {
			// and use this to construct an exporter
			Exporter exporter1 = (Exporter) (config).getEntry(
						"SSLJeriExport", "exporter", Exporter.class);
			// export an object of this class
			proxy = exporter1.export(market_service);
			//export authentication class
			Exporter exporter2 = (Exporter) (config).getEntry(
						"SSLJeriExport", "exporter", Exporter.class);
			authenticateProxy = exporter2.export(authenticate_service);
			//export remote bank class
			Exporter exporter3 = (Exporter) (config).getEntry(
						"JeriExport", "exporter", Exporter.class);
			remoteAccountsProxy = exporter3.export(remote_accounts);
			remote_accounts.setProxy(remoteAccountsProxy);
		} catch(Exception e) {
			System.err.println(e.toString());
			e.printStackTrace();
			System.exit(1);
		}
		try {
			LookupDiscoveryManager mgr = new LookupDiscoveryManager(LookupDiscovery.ALL_GROUPS,
					null, // unicast locators
					null); // DiscoveryListener
			//template
			
			//register market service to LUS
			Entry[] serverAttributes1 = new Entry[1];
		    serverAttributes1[0] = new Name (IAuction.MARKET_SERVICE_NAME);
		    new JoinManager(proxy, // service proxy
				    serverAttributes1, // attr sets
					this, // ServiceIDListener
					mgr, // DiscoveryManager
					new LeaseRenewalManager());
		    
		    //register Authentication service to LUS
			Entry[] serverAttributes2 = new Entry[1];
		    serverAttributes2[0] = new Name (IAuction.AUTHENTICATE_SERVICE_NAME);
		    new JoinManager(authenticateProxy, // service proxy
				    serverAttributes2, // attr sets
					this, // ServiceIDListener
					mgr, // DiscoveryManager
					new LeaseRenewalManager());
			
		    //register remote bank service to LUS
			Entry[] serverAttributes3 = new Entry[1];
		    serverAttributes3[0] = new Name (IAuction.REMOTE_ACCOUNTS_NAME);
		    new JoinManager(remoteAccountsProxy, // service proxy
				    serverAttributes3, // attr sets
					this, // ServiceIDListener
					mgr, // DiscoveryManager
					new LeaseRenewalManager());
		} catch(Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}
	
	public void setCheckPoint() {
		if (market_service != null) {
			try {
				market_service.setCheckPoint();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public void restoreFromCheckPoint() {
		if (market_service != null) {
			try {
				market_service.restoreFromCheckPoint();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	@Override
	public void serviceIDNotify(ServiceID serviceID) {
		// called as a ServiceIDListener
		System.out.println("Service " + serviceID.toString() + " is successfully registered");
	}
}
